{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用TensorFlow构建一个简单的线性分类模型\n",
    "\n",
    "&emsp;&emsp;在这个示例中，将会使用TensorFlow构建一个基本的线性分类模型来对[mnist数据集](http://yann.lecun.com/exdb/mnist/)中的的手写数字进行识别。MNIST数据集是一个经典的分类数据集，它的每个样本是一个28\\*28的灰度图，每个图片展示的是手写数字0~9中的一个，如下图示。\n",
    "\n",
    "![mnist dataset](../img/MNIST.png)\n",
    "\n",
    "任务目标就是识别数字，即将数字正确的分类，采用模型的一些参数如下：\n",
    "\n",
    "+ 模型：softmax回归，即逻辑回归在多分类情况下的推广形式，$p(y=i)=\\frac{e^{-w_ix}}{\\sum_j e^-w_jx}$\n",
    "\n",
    "+ 特征：图片的灰度值特征\n",
    "\n",
    "+ 损失函数：log损失函数 $loss = -\\sum_i I_{i=lable}logp(y=i)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ../data/MNIST_data/train-images-idx3-ubyte.gz\n",
      "Extracting ../data/MNIST_data/train-labels-idx1-ubyte.gz\n",
      "Extracting ../data/MNIST_data/t10k-images-idx3-ubyte.gz\n",
      "Extracting ../data/MNIST_data/t10k-labels-idx1-ubyte.gz\n",
      "Step: 0, Test accuracy: 0.070, timeCos: 1.8\n",
      "Step: 50, Test accuracy: 0.078, timeCos: 6.9\n",
      "Step: 100, Test accuracy: 0.091, timeCos: 1.6\n",
      "Step: 150, Test accuracy: 0.105, timeCos: 1.6\n",
      "Step: 200, Test accuracy: 0.120, timeCos: 1.6\n",
      "Step: 250, Test accuracy: 0.141, timeCos: 2.0\n",
      "Step: 300, Test accuracy: 0.162, timeCos: 1.4\n",
      "Step: 350, Test accuracy: 0.186, timeCos: 1.2\n",
      "Step: 400, Test accuracy: 0.210, timeCos: 1.3\n",
      "Step: 450, Test accuracy: 0.233, timeCos: 3.6\n",
      "Step: 500, Test accuracy: 0.261, timeCos: 1.4\n",
      "Step: 550, Test accuracy: 0.286, timeCos: 1.5\n",
      "Step: 600, Test accuracy: 0.309, timeCos: 1.5\n",
      "Step: 650, Test accuracy: 0.335, timeCos: 1.6\n",
      "Step: 700, Test accuracy: 0.359, timeCos: 1.4\n",
      "Step: 750, Test accuracy: 0.382, timeCos: 1.5\n",
      "Step: 800, Test accuracy: 0.406, timeCos: 1.4\n",
      "Step: 850, Test accuracy: 0.426, timeCos: 1.4\n",
      "Step: 900, Test accuracy: 0.443, timeCos: 3.4\n",
      "Step: 950, Test accuracy: 0.462, timeCos: 1.5\n",
      "Step: 1000, Test accuracy: 0.478, timeCos: 1.4\n",
      "Step: 1050, Test accuracy: 0.497, timeCos: 1.4\n",
      "Step: 1100, Test accuracy: 0.512, timeCos: 1.5\n",
      "Step: 1150, Test accuracy: 0.528, timeCos: 1.4\n",
      "Step: 1200, Test accuracy: 0.543, timeCos: 1.5\n",
      "Step: 1250, Test accuracy: 0.556, timeCos: 1.4\n",
      "Step: 1300, Test accuracy: 0.567, timeCos: 3.5\n",
      "Step: 1350, Test accuracy: 0.580, timeCos: 1.4\n",
      "Step: 1400, Test accuracy: 0.593, timeCos: 1.5\n",
      "Step: 1450, Test accuracy: 0.604, timeCos: 1.4\n",
      "Step: 1500, Test accuracy: 0.613, timeCos: 1.5\n",
      "Step: 1550, Test accuracy: 0.622, timeCos: 1.4\n",
      "Step: 1600, Test accuracy: 0.631, timeCos: 1.4\n",
      "Step: 1650, Test accuracy: 0.640, timeCos: 1.5\n",
      "Step: 1700, Test accuracy: 0.646, timeCos: 1.5\n",
      "Step: 1750, Test accuracy: 0.654, timeCos: 3.4\n",
      "Step: 1800, Test accuracy: 0.660, timeCos: 1.5\n",
      "Step: 1850, Test accuracy: 0.667, timeCos: 1.4\n",
      "Step: 1900, Test accuracy: 0.673, timeCos: 1.5\n",
      "Step: 1950, Test accuracy: 0.680, timeCos: 1.5\n",
      "Step: 2000, Test accuracy: 0.685, timeCos: 1.5\n",
      "Step: 2050, Test accuracy: 0.689, timeCos: 1.5\n",
      "Step: 2100, Test accuracy: 0.694, timeCos: 1.5\n",
      "Step: 2150, Test accuracy: 0.698, timeCos: 3.4\n",
      "Step: 2200, Test accuracy: 0.705, timeCos: 1.4\n",
      "Step: 2250, Test accuracy: 0.709, timeCos: 1.4\n",
      "Step: 2300, Test accuracy: 0.713, timeCos: 1.4\n",
      "Step: 2350, Test accuracy: 0.716, timeCos: 1.5\n",
      "Step: 2400, Test accuracy: 0.719, timeCos: 1.5\n",
      "Step: 2450, Test accuracy: 0.721, timeCos: 1.5\n",
      "Step: 2500, Test accuracy: 0.724, timeCos: 1.4\n",
      "Step: 2550, Test accuracy: 0.727, timeCos: 1.5\n",
      "Step: 2600, Test accuracy: 0.729, timeCos: 3.4\n",
      "Step: 2650, Test accuracy: 0.732, timeCos: 1.4\n",
      "Step: 2700, Test accuracy: 0.735, timeCos: 1.5\n",
      "Step: 2750, Test accuracy: 0.738, timeCos: 1.4\n",
      "Step: 2800, Test accuracy: 0.740, timeCos: 1.4\n",
      "Step: 2850, Test accuracy: 0.743, timeCos: 1.5\n",
      "Step: 2900, Test accuracy: 0.745, timeCos: 1.4\n",
      "Step: 2950, Test accuracy: 0.747, timeCos: 1.5\n",
      "Step: 3000, Test accuracy: 0.750, timeCos: 1.5\n",
      "Step: 3050, Test accuracy: 0.752, timeCos: 3.5\n",
      "Step: 3100, Test accuracy: 0.755, timeCos: 1.5\n",
      "Step: 3150, Test accuracy: 0.758, timeCos: 1.5\n",
      "Step: 3200, Test accuracy: 0.760, timeCos: 1.6\n",
      "Step: 3250, Test accuracy: 0.763, timeCos: 2.0\n",
      "Step: 3300, Test accuracy: 0.764, timeCos: 1.6\n",
      "Step: 3350, Test accuracy: 0.765, timeCos: 1.6\n",
      "Step: 3400, Test accuracy: 0.767, timeCos: 1.7\n",
      "Step: 3450, Test accuracy: 0.770, timeCos: 3.6\n",
      "Step: 3500, Test accuracy: 0.772, timeCos: 1.5\n",
      "Step: 3550, Test accuracy: 0.773, timeCos: 1.6\n",
      "Step: 3600, Test accuracy: 0.775, timeCos: 1.6\n",
      "Step: 3650, Test accuracy: 0.776, timeCos: 1.6\n",
      "Step: 3700, Test accuracy: 0.778, timeCos: 1.5\n",
      "Step: 3750, Test accuracy: 0.779, timeCos: 1.5\n",
      "Step: 3800, Test accuracy: 0.780, timeCos: 1.5\n",
      "Step: 3850, Test accuracy: 0.781, timeCos: 1.5\n",
      "Step: 3900, Test accuracy: 0.783, timeCos: 3.5\n",
      "Step: 3950, Test accuracy: 0.785, timeCos: 1.5\n",
      "Step: 4000, Test accuracy: 0.785, timeCos: 1.5\n",
      "Step: 4050, Test accuracy: 0.786, timeCos: 1.5\n",
      "Step: 4100, Test accuracy: 0.788, timeCos: 1.5\n",
      "Step: 4150, Test accuracy: 0.788, timeCos: 1.4\n",
      "Step: 4200, Test accuracy: 0.789, timeCos: 1.4\n",
      "Step: 4250, Test accuracy: 0.791, timeCos: 1.4\n",
      "Step: 4300, Test accuracy: 0.792, timeCos: 3.5\n",
      "Step: 4350, Test accuracy: 0.793, timeCos: 1.4\n",
      "Step: 4400, Test accuracy: 0.795, timeCos: 1.5\n",
      "Step: 4450, Test accuracy: 0.795, timeCos: 1.6\n",
      "Step: 4500, Test accuracy: 0.797, timeCos: 1.5\n",
      "Step: 4550, Test accuracy: 0.798, timeCos: 1.5\n",
      "Step: 4600, Test accuracy: 0.798, timeCos: 1.5\n",
      "Step: 4650, Test accuracy: 0.800, timeCos: 1.4\n",
      "Step: 4700, Test accuracy: 0.800, timeCos: 1.4\n",
      "Step: 4750, Test accuracy: 0.801, timeCos: 3.2\n",
      "Step: 4800, Test accuracy: 0.802, timeCos: 1.3\n",
      "Step: 4850, Test accuracy: 0.803, timeCos: 1.4\n",
      "Step: 4900, Test accuracy: 0.804, timeCos: 1.4\n",
      "Step: 4950, Test accuracy: 0.805, timeCos: 1.5\n",
      "Step: 5000, Test accuracy: 0.806, timeCos: 1.5\n",
      "Step: 5050, Test accuracy: 0.807, timeCos: 1.5\n",
      "Step: 5100, Test accuracy: 0.808, timeCos: 1.5\n",
      "Step: 5150, Test accuracy: 0.809, timeCos: 1.6\n",
      "Step: 5200, Test accuracy: 0.809, timeCos: 3.5\n",
      "Step: 5250, Test accuracy: 0.810, timeCos: 1.5\n",
      "Step: 5300, Test accuracy: 0.811, timeCos: 1.6\n",
      "Step: 5350, Test accuracy: 0.812, timeCos: 1.6\n",
      "Step: 5400, Test accuracy: 0.813, timeCos: 1.6\n",
      "Step: 5450, Test accuracy: 0.814, timeCos: 1.5\n",
      "Step: 5500, Test accuracy: 0.814, timeCos: 1.5\n",
      "Step: 5550, Test accuracy: 0.815, timeCos: 1.7\n",
      "Step: 5600, Test accuracy: 0.815, timeCos: 3.7\n",
      "Step: 5650, Test accuracy: 0.815, timeCos: 1.6\n",
      "Step: 5700, Test accuracy: 0.816, timeCos: 1.6\n",
      "Step: 5750, Test accuracy: 0.817, timeCos: 1.5\n",
      "Step: 5800, Test accuracy: 0.818, timeCos: 1.4\n",
      "Step: 5850, Test accuracy: 0.818, timeCos: 1.5\n",
      "Step: 5900, Test accuracy: 0.819, timeCos: 1.4\n",
      "Step: 5950, Test accuracy: 0.820, timeCos: 1.4\n",
      "Step: 6000, Test accuracy: 0.821, timeCos: 1.4\n",
      "Step: 6050, Test accuracy: 0.822, timeCos: 3.5\n",
      "Step: 6100, Test accuracy: 0.822, timeCos: 2.1\n",
      "Step: 6150, Test accuracy: 0.822, timeCos: 1.7\n",
      "Step: 6200, Test accuracy: 0.823, timeCos: 1.6\n",
      "Step: 6250, Test accuracy: 0.824, timeCos: 1.6\n",
      "Step: 6300, Test accuracy: 0.824, timeCos: 1.6\n",
      "Step: 6350, Test accuracy: 0.825, timeCos: 1.6\n",
      "Step: 6400, Test accuracy: 0.825, timeCos: 1.5\n",
      "Step: 6450, Test accuracy: 0.825, timeCos: 3.5\n",
      "Step: 6500, Test accuracy: 0.825, timeCos: 1.4\n",
      "Step: 6550, Test accuracy: 0.827, timeCos: 1.5\n",
      "Step: 6600, Test accuracy: 0.826, timeCos: 1.6\n",
      "Step: 6650, Test accuracy: 0.827, timeCos: 1.6\n",
      "Step: 6700, Test accuracy: 0.828, timeCos: 1.5\n",
      "Step: 6750, Test accuracy: 0.828, timeCos: 1.6\n",
      "Step: 6800, Test accuracy: 0.828, timeCos: 1.6\n",
      "Step: 6850, Test accuracy: 0.829, timeCos: 1.6\n",
      "Step: 6900, Test accuracy: 0.829, timeCos: 3.6\n",
      "Step: 6950, Test accuracy: 0.829, timeCos: 1.6\n",
      "Step: 7000, Test accuracy: 0.829, timeCos: 1.5\n",
      "Step: 7050, Test accuracy: 0.830, timeCos: 1.7\n",
      "Step: 7100, Test accuracy: 0.831, timeCos: 1.5\n",
      "Step: 7150, Test accuracy: 0.831, timeCos: 1.7\n",
      "Step: 7200, Test accuracy: 0.832, timeCos: 1.7\n",
      "Step: 7250, Test accuracy: 0.833, timeCos: 1.7\n",
      "Step: 7300, Test accuracy: 0.833, timeCos: 1.7\n",
      "Step: 7350, Test accuracy: 0.834, timeCos: 3.6\n",
      "Step: 7400, Test accuracy: 0.835, timeCos: 1.6\n",
      "Step: 7450, Test accuracy: 0.835, timeCos: 1.6\n",
      "Step: 7500, Test accuracy: 0.835, timeCos: 1.6\n",
      "Step: 7550, Test accuracy: 0.836, timeCos: 1.6\n",
      "Step: 7600, Test accuracy: 0.836, timeCos: 1.7\n",
      "Step: 7650, Test accuracy: 0.837, timeCos: 1.5\n",
      "Step: 7700, Test accuracy: 0.837, timeCos: 1.3\n",
      "Step: 7750, Test accuracy: 0.837, timeCos: 3.0\n",
      "Step: 7800, Test accuracy: 0.838, timeCos: 1.3\n",
      "Step: 7850, Test accuracy: 0.838, timeCos: 1.3\n",
      "Step: 7900, Test accuracy: 0.839, timeCos: 1.3\n",
      "Step: 7950, Test accuracy: 0.840, timeCos: 1.3\n",
      "Step: 8000, Test accuracy: 0.840, timeCos: 1.3\n",
      "Step: 8050, Test accuracy: 0.840, timeCos: 1.3\n",
      "Step: 8100, Test accuracy: 0.840, timeCos: 1.3\n",
      "Step: 8150, Test accuracy: 0.840, timeCos: 1.3\n",
      "Step: 8200, Test accuracy: 0.841, timeCos: 2.8\n",
      "Step: 8250, Test accuracy: 0.841, timeCos: 1.4\n",
      "Step: 8300, Test accuracy: 0.841, timeCos: 1.4\n",
      "Step: 8350, Test accuracy: 0.842, timeCos: 1.4\n",
      "Step: 8400, Test accuracy: 0.842, timeCos: 1.4\n",
      "Step: 8450, Test accuracy: 0.842, timeCos: 1.4\n",
      "Step: 8500, Test accuracy: 0.843, timeCos: 1.5\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Step: 8550, Test accuracy: 0.843, timeCos: 1.5\n",
      "Step: 8600, Test accuracy: 0.843, timeCos: 3.6\n",
      "Step: 8650, Test accuracy: 0.844, timeCos: 1.4\n",
      "Step: 8700, Test accuracy: 0.844, timeCos: 1.5\n",
      "Step: 8750, Test accuracy: 0.844, timeCos: 1.4\n",
      "Step: 8800, Test accuracy: 0.844, timeCos: 1.4\n",
      "Step: 8850, Test accuracy: 0.844, timeCos: 1.5\n",
      "Step: 8900, Test accuracy: 0.844, timeCos: 1.4\n",
      "Step: 8950, Test accuracy: 0.845, timeCos: 1.4\n",
      "Step: 9000, Test accuracy: 0.845, timeCos: 1.6\n",
      "Step: 9050, Test accuracy: 0.845, timeCos: 4.2\n",
      "Step: 9100, Test accuracy: 0.846, timeCos: 1.5\n",
      "Step: 9150, Test accuracy: 0.846, timeCos: 1.6\n",
      "Step: 9200, Test accuracy: 0.846, timeCos: 1.5\n",
      "Step: 9250, Test accuracy: 0.846, timeCos: 1.4\n",
      "Step: 9300, Test accuracy: 0.847, timeCos: 1.4\n",
      "Step: 9350, Test accuracy: 0.847, timeCos: 1.5\n",
      "Step: 9400, Test accuracy: 0.847, timeCos: 1.5\n",
      "Step: 9450, Test accuracy: 0.847, timeCos: 1.6\n",
      "Step: 9500, Test accuracy: 0.847, timeCos: 3.4\n",
      "Step: 9550, Test accuracy: 0.848, timeCos: 1.4\n",
      "Step: 9600, Test accuracy: 0.848, timeCos: 1.6\n",
      "Step: 9650, Test accuracy: 0.848, timeCos: 1.6\n",
      "Step: 9700, Test accuracy: 0.848, timeCos: 1.5\n",
      "Step: 9750, Test accuracy: 0.848, timeCos: 1.4\n",
      "Step: 9800, Test accuracy: 0.849, timeCos: 1.4\n",
      "Step: 9850, Test accuracy: 0.849, timeCos: 1.3\n",
      "Step: 9900, Test accuracy: 0.849, timeCos: 3.3\n",
      "Step: 9950, Test accuracy: 0.849, timeCos: 1.5\n",
      "Step: 10000, Test accuracy: 0.850, timeCos: 1.4\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "import tensorflow as tf\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "\n",
    "mnist = input_data.read_data_sets(\"../data/MNIST_data/\", one_hot=True)\n",
    "\n",
    "# 参量设置\n",
    "batch_size = 128 \n",
    "image_size = 28*28\n",
    "label_num = 10\n",
    "step_size = 0.001\n",
    "max_steps= 10000\n",
    "\n",
    "# 每个样本特征和标签的占位表示\n",
    "x = tf.placeholder(tf.float32, [None, image_size])\n",
    "y_real = tf.placeholder(tf.float32, [None, label_num])\n",
    "\n",
    "# 构建模型\n",
    "w = tf.Variable(tf.truncated_normal(shape=(image_size, label_num), stddev=0.1), name=\"weight\")\n",
    "b = tf.Variable(tf.zeros(shape=label_num), name=\"bias\")\n",
    "p = tf.nn.softmax(tf.matmul(x, w) + b, dim=1)\n",
    "\n",
    "# softmax损失\n",
    "loss = tf.reduce_sum(-y_real*tf.log(p))/batch_size\n",
    "\n",
    "# 准确度\n",
    "correct_prediction = tf.equal(tf.argmax(p, 1), tf.argmax(y_real, 1))\n",
    "accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))\n",
    "\n",
    "# 使用梯度下降更新\n",
    "update = tf.train.GradientDescentOptimizer(step_size).minimize(loss)\n",
    "\n",
    "# 初始化操作\n",
    "init_op = tf.global_variables_initializer()\n",
    "\n",
    "# 迭代更新\n",
    "with tf.Session() as sess:\n",
    "    sess.run(init_op)\n",
    "    start = time.time()\n",
    "    for i in range(max_steps+1):\n",
    "        xs, ys = mnist.train.next_batch(batch_size)\n",
    "        if i % 50 == 0:\n",
    "            timeCos = time.time() - start\n",
    "            start = time.time()\n",
    "            print(\"Step: {:d}, Test accuracy: {:.3f}, timeCos: {:.1f}\".\n",
    "                  format(i, sess.run(accuracy,feed_dict={x: mnist.test.images,\n",
    "                                                         y_real: mnist.test.labels}),\n",
    "                         timeCos* 1000 / 50))\n",
    "        sess.run(update, feed_dict={x: xs, y_real: ys})\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
